/*
 * Copyright 2017 wshunli
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.basemap.tianditu;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;

import com.basemap.api.BaseMapApi;
import com.basemap.api.MapApi;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.FutureTarget;
import com.esri.arcgisruntime.arcgisservices.TileInfo;
import com.esri.arcgisruntime.data.TileKey;
import com.esri.arcgisruntime.geometry.Envelope;
import com.esri.arcgisruntime.layers.ImageTiledLayer;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutionException;

public class TianDiTuLayer extends ImageTiledLayer {

    private static final String TAG = "TianDiTuLayer";

    private int layerType = 0;
    private String cachePath = null;
    private TianDiTuLayerInfo layerInfo;
    private String token = null;
    private String type = null;
    private Context context = null;

    public TianDiTuLayer(TileInfo tileInfo, Envelope fullExtent) {
        super(tileInfo, fullExtent);
    }

    @Override
    protected byte[] getTile(TileKey tileKey) {

        if (this.getToken() == null) {
//            Log.e(TAG, "Please set the token value. See http://lbs.tianditu.gov.cn/authorization/authorization.html");
        }
        int level = tileKey.getLevel();
        int col = tileKey.getColumn();
        int row = tileKey.getRow();
        if (level > layerInfo.getMaxZoomLevel()
                || level < layerInfo.getMinZoomLevel())
            return new byte[0];

        byte[] bytes = null;
        if (cachePath != null) {
            if (!new File(cachePath).exists()) new File(cachePath).mkdir();
            bytes = getOfflineCacheFile(cachePath, level, col, row);
        }
        if (bytes == null) {
            String url = null;
            if (token != null) {
                //范围线
                if (type.equals("fwx") && level > 8) {
                    url = layerInfo.getUrl()
                            + "?service=wmts&request=gettile&version=1.0.0&style=default&layer="
                            + layerInfo.getLayerName() + "&format=image/jpeg&tilematrixset="
                            + layerInfo.getTileMatrixSet() + "&tilecol=" + col
                            + "&tilerow=" + row + "&tilematrix=" + layerInfo.getTileMatrixSet() + ":" + (level) + "&token=" + token;
                    FutureTarget<File> submit = null;
                    submit = Glide.with(context)
                            .asFile()
                            .load(url)
                            .submit();
                    try {
                        File file = submit.get();
                        try {
                            FileInputStream inputStream = new FileInputStream(file);
                            bytes = getBytes(inputStream);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                    if (bytes != null) {
                        try {
                            InputStream is = context.getResources().getAssets().open("fwx_null.png");
                            byte[] bytes_null = getBytes(is);
                            if (bytes.length != bytes_null.length) {
                                if (cachePath != null) {
                                    AddOfflineCacheFile(cachePath, level, col, row, bytes, type);
                                }
                            }

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }


                }
                //注记
                else if (type.equals("tianditu"))
                    url = layerInfo.getUrl() + "?service=wmts&request=gettile&version=1.0.0&style=default&tk=" + token + "&layer="
                            + layerInfo.getLayerName() + "&format=tiles&tilematrixset="
                            + layerInfo.getTileMatrixSet() + "&tilecol=" + col
                            + "&tilerow=" + row + "&tilematrix=" + (level);
//                    Log.d("ZJurl",url);

                FutureTarget<File> submit = null;
                submit = Glide.with(context)
                        .asFile()
                        .load(url)
                        .error((Drawable) null)
                        .submit();
                try {
                    File file = submit.get();
                    try {
                        FileInputStream inputStream = new FileInputStream(file);
                        bytes = getBytes(inputStream);
                        if (cachePath != null) {
                            AddOfflineCacheFile(cachePath, level, col, row, bytes, type);
                        }
                    } catch (IOException e) {
//                    Log.d("IOException",e.toString());
//                        e.printStackTrace();
                    }
                } catch (InterruptedException | ExecutionException e) {
//                    e.printStackTrace();
                }
            } else {
                //贵州天地图
                String key = "b1b55f2720244fd6b6c2ba46a3f3a6be";
                if (MapApi.gjTdtTK!= null) {
                    key = MapApi.gjTdtTK;
                }
                url = layerInfo.getUrl()
                        + "?key=" + key + "&service=wmts&request=gettile&version=1.0.0&style=default&layer="
                        + layerInfo.getLayerName() + "&format=tiles&tilematrixset="
                        + layerInfo.getTileMatrixSet() + "&tilecol=" + col
                        + "&tilerow=" + row + "&tilematrix=" + (level);

                FutureTarget<File> submit = null;
                submit = Glide.with(context)
                        .asFile()
                        .load(url)
                        .error((Drawable) null)
                        .submit();
                try {
                    File file = submit.get();
                    try {
                        FileInputStream inputStream = new FileInputStream(file);
                        bytes = getBytes(inputStream);
                        if (cachePath != null) {
                            AddOfflineCacheFile(cachePath, level, col, row, bytes, type);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }

            }


        }
        return bytes;
    }


    // 保存切片到本地
    private void AddOfflineCacheFile(String cachePath, int level, int col, int row, byte[] bytes, String type) {
        //范围线100万比例尺开始缓存
        if (type.equals("范围线") && level > 8) {
            File file = new File(cachePath);
            if (!file.exists()) file.mkdirs();
            File levelFile = new File(cachePath + "/" + level);
            if (!levelFile.exists()) levelFile.mkdirs();
            File rowFile = new File(new StringBuilder().append(cachePath).append("/").append(level).append("/").append(row).append("x").append(col).append(".tdt").toString());

            if (!rowFile.exists() && bytes != null) {
                Bitmap mBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);// bitmap

                BufferedOutputStream bos = null;
                try {
                    bos = new BufferedOutputStream(new FileOutputStream(rowFile));
                    mBitmap.compress(Bitmap.CompressFormat.PNG, 80, bos);
                    bos.flush();
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
        //影像不做控制
        else {
            File file = new File(cachePath);
            if (!file.exists()) file.mkdirs();
            File levelFile = new File(cachePath + "/" + level);
            if (!levelFile.exists()) levelFile.mkdirs();
            File rowFile = new File(new StringBuilder().append(cachePath).append("/").append(level).append("/").append(row).append("x").append(col).append(".tdt").toString());

            if (!rowFile.exists() && bytes != null) {
                Bitmap mBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);// bitmap

                BufferedOutputStream bos = null;
                try {
                    bos = new BufferedOutputStream(new FileOutputStream(rowFile));
                    mBitmap.compress(Bitmap.CompressFormat.PNG, 80, bos);
                    bos.flush();
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

    }

    // 从本地获取切片
    private byte[] getOfflineCacheFile(String cachePath, int level, int col, int row) {
        byte[] bytes = null;
        File rowFile = new File(cachePath + "/" + level + "/" + row + "x" + col + ".tdt");
        if (rowFile.exists()) {
            try {
                FileInputStream in = new FileInputStream(rowFile);
                bytes = getBytes(in);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bytes;
    }

    // 读取字节数组
    private byte[] getBytes(InputStream is) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
        byte[] temp = new byte[1024];
        int size;
        while ((size = is.read(temp)) != -1) {
            out.write(temp, 0, size);
        }
        is.close();
        out.flush();
        return out.toByteArray();
    }

    public int getLayerType() {
        return layerType;
    }

    public void setLayerType(int layerType) {
        this.layerType = layerType;
        this.layerInfo = LayerInfoFactory.getLayerInfo(layerType);
    }

    public String getCachePath() {
        return cachePath;
    }

    public void setCachePath(String cachePath) {
        this.cachePath = cachePath == null ? null : cachePath + layerInfo.getLayerName() + "_" + layerInfo.getTileMatrixSet();
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public void setContext(Context context) {
        this.context = context;
    }
}
